/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc8_tti_dcb.c                                 */
/*  NOTE      =                                                    */
/*  DATE      = 2014/10/23 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frcomm.h"
#include "frstr.h"
#include "frmem.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_stmt.h"
#include "../../comm/ora_util.h"
#include "../ora_mar_engine.h"
#include "ora_ttc8_tti_uds.h"
#include "ora_ttc8_tti_dcb.h"

/*******************************************************************************
*  FUNC     :  对应于 Accessor[] receiveCommon(Accessor[] paramArrayOfAccessor, boolean paramBoolean) 方法
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  i_boolean
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc8_tti_dcb_receiveCommon(Conntrack *p_st_conn
                                            , L7session_ora *p_st_sess
                                            , L7_ora_packet *p_st_ora_packet
                                            , int i_boolean
                                            , Sql_statement *p_st_stmt)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;

    short s_tmp = 0;
    long long ll_tmp = 0LL;
    long long ll_k = 0LL;
    long long ll_m = 0LL;
    long long ll_n = 0LL;
    long long ll_i1 = 0LL;
    int i_numuds = 0; // 列的个数
    int i_loop = 0;
    int i_analyze_start_pos = 0;
    int i_ttc8_stmt_resp_dcbkm_old = p_st_sess->i_ttc8_stmt_resp_dcbkm;
    int i_ttc8_stmt_resp_dcbni1_old = p_st_sess->i_ttc8_stmt_resp_dcbni1;
    int i_ttc8_stmt_resp_dcbab2_old = p_st_sess->i_ttc8_stmt_resp_dcbab2;

    if (i_boolean)
    {
        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_numuds) != FR_SUCC) // numuds
            goto error;
    }
    else
    {
        if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // numuds
            goto error;
        i_numuds = (int) ll_tmp;
        if (i_numuds > 0)
        {
            if (ora_mar_skipUB1(p_st_ora_packet) != FR_SUCC) // i
                goto error;
        }
    }

	frdb_set_column_nums(p_st_stmt, i_numuds);
    ORA_PRINT_DBG("set i_column_nums:[%d]\n", frdb_get_column_nums(p_st_stmt));
    memset(p_st_curr_sess->arr_columns_bit, 0, BITLEN(p_st_curr_sess->arr_columns_bit));

    p_st_curr_sess->i_null_num = 0;

    frlist_remove_all(&(p_st_stmt->st_metadata_column), frdb_metadata_node_free);
    frlist_remove_all(&(p_st_stmt->st_metadata_define), frdb_metadata_node_free);

    if (p_st_sess->i_use_special_field == FR_YES && (
          p_st_sess->i_ttc8_stmt_resp_udskpos == APM_ORA_FLAG_UNSET ||
          p_st_sess->i_ttc8_stmt_resp_udsflg == APM_ORA_FLAG_UNSET ||
          p_st_sess->i_ttc8_stmt_resp_oac_skip1 == APM_ORA_FLAG_UNSET ||
          p_st_sess->i_ttc8_stmt_resp_oac_skipaftervsn == APM_ORA_FLAG_UNSET))
    {
        int i_pos = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
        if (ora_ttc8_tti_uds_analyze_oci(p_st_conn, p_st_sess, p_st_ora_packet, i_numuds) != FR_SUCC)
            goto error;
        bytebuff_setPosition(p_st_ora_packet->p_st_packet, i_pos);
    }
    for (i_loop = 0; i_loop < i_numuds; i_loop++)
    {
        if (ora_ttc8_tti_uds_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, p_st_stmt, i_loop, i_numuds) != FR_SUCC)
            goto error;
    }

    if (!i_boolean)
    {
        if (p_st_sess->i_ttc8_stmt_resp_udskpos == APM_ORA_FLAG_UNSET || p_st_sess->i_ttc8_stmt_resp_udsflg == APM_ORA_FLAG_UNSET)
            goto error;

        if (ora_mar_skipDALC(p_st_sess, p_st_ora_packet) != FR_SUCC) // arrayOfByte1
            goto error;

        if (p_st_sess->i_ttc8_stmt_resp_dcbkm == APM_ORA_FLAG_UNSET ||
                p_st_sess->i_ttc8_stmt_resp_dcbni1 == APM_ORA_FLAG_UNSET ||
                p_st_sess->i_ttc8_stmt_resp_dcbab2 == APM_ORA_FLAG_UNSET)
        {
            i_analyze_start_pos = bytebuff_getPosition(p_st_ora_packet->p_st_packet);
            if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_k) != FR_SUCC) // k
            {
                p_st_sess->i_ttc8_stmt_resp_dcbkm = FR_NO;
                p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_NO;
                p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
                goto analyze_success;
            }
            if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_m) != FR_SUCC) // m
            {
                p_st_sess->i_ttc8_stmt_resp_dcbkm = FR_NO;
                p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_NO;
                p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
                goto analyze_success;
            }
            if (p_st_sess->i_ttc8_stmt_resp_dcbkm == FR_YES || (p_st_sess->i_ttc8_stmt_resp_dcbkm == APM_ORA_FLAG_UNSET && (ll_k == 0 || ll_k == 1) && ll_m == 0x1fe8))
            {
                p_st_sess->i_ttc8_stmt_resp_dcbkm = FR_YES;

                if (ora_mar_peekUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                    goto error;
                if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_n) != FR_SUCC) // n
                {
                    p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_NO;
                    p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
                    goto analyze_success;
                }
                if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_i1) != FR_SUCC) // i1
                {
                    p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_NO;
                    p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
                    goto analyze_success;
                }

                if (s_tmp != 0x06 && s_tmp != 0x08 && ll_n == ll_i1)
                {
                    p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_YES;
                    if (ora_mar_peekUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                        goto error;
                    if (s_tmp == 0x00)
                        p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_YES;
                    else
                        p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
                }
                else
                {
                    p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_NO;
                    p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
                }
            }
            else
            {
                p_st_sess->i_ttc8_stmt_resp_dcbkm = FR_NO;
                p_st_sess->i_ttc8_stmt_resp_dcbni1 = FR_NO;
                p_st_sess->i_ttc8_stmt_resp_dcbab2 = FR_NO;
            }

analyze_success:
            bytebuff_setPosition(p_st_ora_packet->p_st_packet, i_analyze_start_pos);

            ORA_PRINT_ALERT("set i_ttc8_stmt_resp_dcbkm = %s, i_ttc8_stmt_resp_dcbni1 = %s, i_ttc8_stmt_resp_dcbab2 = %s\n",
                            p_st_sess->i_ttc8_stmt_resp_dcbkm == APM_ORA_FLAG_UNSET ? "UNSET" : (p_st_sess->i_ttc8_stmt_resp_dcbkm == FR_YES ? "FR_YES" : "FR_NO"),
                            p_st_sess->i_ttc8_stmt_resp_dcbni1 == APM_ORA_FLAG_UNSET ? "UNSET" : (p_st_sess->i_ttc8_stmt_resp_dcbni1 == FR_YES ? "FR_YES" : "FR_NO"),
                            p_st_sess->i_ttc8_stmt_resp_dcbab2 == APM_ORA_FLAG_UNSET ? "UNSET" : (p_st_sess->i_ttc8_stmt_resp_dcbab2 == FR_YES ? "FR_YES" : "FR_NO"));
        }


        if (p_st_sess->i_ttc8_stmt_resp_dcbkm == FR_YES || (p_st_sess->i_use_special_field == FR_YES && p_st_sess->s_tns_version >= 313))
        {
            ORA_PRINT_INFO("unmarshal k m\n");
            if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // k
                goto error;
            if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // m
                goto error;

            if (p_st_sess->i_ttc8_stmt_resp_dcbni1 == FR_YES || p_st_sess->i_use_special_field == FR_YES)
            {
                ORA_PRINT_INFO("unmarshal n i1\n");
                if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // n
                    goto error;
                if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC) // i1
                    goto error;
                if (p_st_sess->i_ttc8_stmt_resp_dcbab2 == FR_YES || (p_st_sess->i_use_special_field == FR_YES && p_st_sess->s_tns_version >= 314))
                {
                    ORA_PRINT_INFO("unmarshal arrayOfByte2\n");
                    if (ora_mar_skipDALC(p_st_sess, p_st_ora_packet) != FR_SUCC) // arrayOfByte2
                        goto error;
                }
            }
        }
    }

    if (p_st_sess->i_ttc8_stmt_resp_oerendseq == APM_ORA_FLAG_UNSET)
        p_st_sess->i_ttc8_stmt_resp_oerendseq = p_st_sess->i_ttc8_stmt_resp_dcbkm;

    return FR_SUCC;
error:
    if (ora_packet_is_in_fragment(p_st_ora_packet))
    {
        frlist_remove_all(&(p_st_stmt->st_metadata_column), frdb_metadata_node_free);
    }
    p_st_sess->i_ttc8_stmt_resp_dcbkm = i_ttc8_stmt_resp_dcbkm_old;
    p_st_sess->i_ttc8_stmt_resp_dcbni1 = i_ttc8_stmt_resp_dcbni1_old;
    p_st_sess->i_ttc8_stmt_resp_dcbab2 = i_ttc8_stmt_resp_dcbab2_old;
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  对应于 Accessor[] receive(Accessor[] paramArrayOfAccessor) 方法
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc8_tti_dcb_receive(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet
                            , Sql_statement *p_st_stmt)
{
    short s_ignoreBuff_len = 0;
    long long ll_ignoreBuff_len = 0LL;
    uint64_t uint64_tmp1 = 0LL;
    uint64_t uint64_tmp2 = 0LL;
    int i_ttc8_stmt_resp_dcb_recv_old = p_st_sess->i_ttc8_stmt_resp_dcb_recv;

    if (p_st_sess->i_ttc8_stmt_resp_dcb_recv == APM_ORA_FLAG_UNSET)
    {
        if (p_st_sess->i_use_oci == FR_NO)
            p_st_sess->i_ttc8_stmt_resp_dcb_recv = FR_NO;
        else
        {
            if (bytebuff_peek_long(p_st_ora_packet->p_st_packet, 4, &uint64_tmp1, BYTE_BIG_ENDIAN) != FR_SUCC)
                goto error;
            if (bytebuff_peek_long(p_st_ora_packet->p_st_packet, 2, &uint64_tmp2, BYTE_BIG_ENDIAN) != FR_SUCC)
                goto error;
            if (uint64_tmp1 == 0x17000000 || uint64_tmp1 == 0x19000000 || uint64_tmp2 == 0x0117 || uint64_tmp2 == 0x0119)
                p_st_sess->i_ttc8_stmt_resp_dcb_recv = FR_YES;
            else
                p_st_sess->i_ttc8_stmt_resp_dcb_recv = FR_NO;
        }
    }

    if (p_st_sess->i_ttc8_stmt_resp_dcb_recv == FR_YES)
    {
        if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_ignoreBuff_len) != FR_SUCC) // i, the length of ignoreBuff
            goto error;

        if (ora_mar_skipNBytes((int) ll_ignoreBuff_len, p_st_ora_packet) != FR_SUCC)
            goto error;
    }
    else
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_ignoreBuff_len) != FR_SUCC) // i, the length of ignoreBuff
            goto error;

        if (ora_mar_skipNBytes(s_ignoreBuff_len, p_st_ora_packet) != FR_SUCC)
            goto error;
    }

    if (ora_mar_skipUB4(p_st_sess, p_st_ora_packet) != FR_SUCC) // j
        goto error;

    if (ora_ttc8_tti_dcb_receiveCommon(p_st_conn, p_st_sess, p_st_ora_packet, FR_NO, p_st_stmt) != FR_SUCC)
        goto error;

    // 返回DCB时dml应为no
    p_st_stmt->i_is_dml = FR_NO;

    return FR_SUCC;
error:
    p_st_sess->i_ttc8_stmt_resp_dcb_recv = i_ttc8_stmt_resp_dcb_recv_old;
    return FR_FAIL;
}
